/*
 * Copyright 2009-2019 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#define BOOST_TEST_MAIN

#define BOOST_TEST_MODULE diis_test
#include <boost/test/unit_test.hpp>
#include <iostream>
#include <votca/xtp/diis.h>

using namespace votca::xtp;

BOOST_AUTO_TEST_SUITE(diis_test)

BOOST_AUTO_TEST_CASE(coeffs_test) {

  DIIS diis;
  diis.setHistLength(5);

  Eigen::MatrixXd error1 = Eigen::MatrixXd::Zero(17, 17);
  error1 << -5.72459e-17, 0.421271, 1.16054e-12, 9.88822e-13, 1.10962e-12,
      0.50196, 4.5521e-13, 3.66001e-13, 4.25776e-13, 0.156112, 0.166066,
      0.156112, 0.166066, 0.156112, 0.166066, 0.156112, 0.166066, -0.421271,
      -2.498e-16, -2.92683e-14, -5.89528e-14, -4.81698e-14, 1.26589,
      -5.89129e-14, -1.95411e-13, -1.22952e-13, 0.472946, 0.397505, 0.472946,
      0.397505, 0.472946, 0.397505, 0.472946, 0.397505, -1.16054e-12,
      2.93376e-14, 7.63278e-17, 5.97439e-15, -1.8735e-15, 1.05584e-13, 1.38874,
      -1.91427e-14, -4.33134e-14, 0.545347, 0.178966, 0.545347, 0.178966,
      -0.545347, -0.178966, -0.545347, -0.178966, -9.88848e-13, 5.89806e-14,
      -5.94663e-15, 1.249e-16, -4.3715e-16, -1.95607e-14, -3.9491e-14, 1.38874,
      1.69812e-14, 0.545347, 0.178966, -0.545347, -0.178966, -0.545347,
      -0.178966, 0.545347, 0.178966, -1.10963e-12, 4.82947e-14, 1.85268e-15,
      3.88578e-16, -1.52656e-16, 5.73395e-14, -4.0223e-14, 1.68242e-14, 1.38874,
      0.545347, 0.178966, -0.545347, -0.178966, 0.545347, 0.178966, -0.545347,
      -0.178966, -0.50196, -1.26589, -1.05749e-13, 1.94844e-14, -5.73985e-14,
      1.16573e-15, -8.18512e-14, -1.13382e-13, -9.86849e-14, 0.0944269,
      -0.025375, 0.0944269, -0.025375, 0.0944269, -0.025375, 0.0944269,
      -0.025375, -4.55275e-13, 5.82867e-14, -1.38874, 3.91354e-14, 4.02456e-14,
      8.18512e-14, -1.249e-16, 4.88498e-15, -1.33227e-15, -0.0078462,
      -0.0361018, -0.0078462, -0.0361018, 0.0078462, 0.0361018, 0.0078462,
      0.0361018, -3.65957e-13, 1.95843e-13, 1.92624e-14, -1.38874, -1.68754e-14,
      1.13132e-13, -4.89886e-15, -2.15106e-16, 8.67362e-16, -0.0078462,
      -0.0361018, 0.0078462, 0.0361018, 0.0078462, 0.0361018, -0.0078462,
      -0.0361018, -4.25771e-13, 1.2268e-13, 4.34097e-14, -1.68199e-14, -1.38874,
      9.85184e-14, 1.2837e-15, -8.67362e-16, 4.85723e-17, -0.0078462,
      -0.0361018, 0.0078462, 0.0361018, -0.0078462, -0.0361018, 0.0078462,
      0.0361018, -0.156112, -0.472946, -0.545347, -0.545347, -0.545347,
      -0.0944269, 0.0078462, 0.0078462, 0.0078462, 7.71952e-17, -0.0786286,
      -2.91807e-14, -0.0259657, -2.69637e-14, -0.0259657, -2.87721e-14,
      -0.0259657, -0.166066, -0.397505, -0.178966, -0.178966, -0.178966,
      0.025375, 0.0361018, 0.0361018, 0.0361018, 0.0786286, -2.34188e-17,
      0.0259657, -2.7949e-14, 0.0259657, -2.46756e-14, 0.0259657, -2.28238e-14,
      -0.156112, -0.472946, -0.545347, 0.545347, 0.545347, -0.0944269,
      0.0078462, -0.0078462, -0.0078462, 2.91954e-14, -0.0259657, -7.80626e-18,
      -0.0786286, 9.72313e-15, -0.0259657, 7.13839e-15, -0.0259657, -0.166066,
      -0.397505, -0.178966, 0.178966, 0.178966, 0.025375, 0.0361018, -0.0361018,
      -0.0361018, 0.0259657, 2.8047e-14, 0.0786286, -5.46438e-17, 0.0259657,
      4.62737e-15, 0.0259657, 6.36297e-15, -0.156112, -0.472946, 0.545347,
      0.545347, -0.545347, -0.0944269, -0.0078462, -0.0078462, 0.0078462,
      2.69862e-14, -0.0259657, -9.70144e-15, -0.0259657, 5.20417e-18,
      -0.0786286, 1.13156e-14, -0.0259657, -0.166066, -0.397505, 0.178966,
      0.178966, -0.178966, 0.025375, -0.0361018, -0.0361018, 0.0361018,
      0.0259657, 2.46097e-14, 0.0259657, -4.60656e-15, 0.0786286, 4.85723e-17,
      0.0259657, 2.6641e-15, -0.156112, -0.472946, 0.545347, -0.545347,
      0.545347, -0.0944269, -0.0078462, 0.0078462, -0.0078462, 2.87617e-14,
      -0.0259657, -7.16094e-15, -0.0259657, -1.12965e-14, -0.0259657,
      -8.32667e-17, -0.0786286, -0.166066, -0.397505, 0.178966, -0.178966,
      0.178966, 0.025375, -0.0361018, 0.0361018, -0.0361018, 0.0259657,
      2.28706e-14, 0.0259657, -6.32827e-15, 0.0259657, -2.65066e-15, 0.0786286,
      -1.11022e-16;

  diis.Update(0, error1);

  Eigen::MatrixXd error2 = Eigen::MatrixXd::Zero(17, 17);
  error2 << -2.51535e-17, 0.205521, 8.26338e-13, 7.18129e-13, 7.93573e-13,
      0.243239, 3.58892e-13, 3.05159e-13, 3.40282e-13, 0.0733301, 0.0756726,
      0.0733301, 0.0756726, 0.0733301, 0.0756726, 0.0733301, 0.0756726,
      -0.205521, -9.71445e-17, -7.9152e-14, -9.96217e-14, -9.34253e-14,
      0.606644, -7.45523e-14, -1.49427e-13, -1.09844e-13, 0.21304, 0.159214,
      0.21304, 0.159214, 0.21304, 0.159214, 0.21304, 0.159214, -8.26348e-13,
      7.9152e-14, 1.249e-16, 3.32373e-15, -1.08941e-15, 1.72229e-13, 0.665049,
      -6.61657e-13, -6.73987e-13, 0.250896, 0.0655191, 0.250896, 0.0655191,
      -0.250896, -0.0655191, -0.250896, -0.0655191, -7.1813e-13, 9.96356e-14,
      -3.32026e-15, 2.08167e-17, -3.22659e-16, 9.39544e-14, -6.74565e-13,
      0.665049, -6.42454e-13, 0.250896, 0.0655191, -0.250896, -0.0655191,
      -0.250896, -0.0655191, 0.250896, 0.0655191, -7.93567e-13, 9.34634e-14,
      1.09635e-15, 2.98372e-16, -1.73472e-17, 1.37192e-13, -6.70585e-13,
      -6.42393e-13, 0.665049, 0.250896, 0.0655191, -0.250896, -0.0655191,
      0.250896, 0.0655191, -0.250896, -0.0655191, -0.243239, -0.606644,
      -1.72307e-13, -9.39249e-14, -1.37251e-13, 1.11022e-16, -1.91423e-13,
      -2.08285e-13, -1.98681e-13, 0.0367454, -0.0343107, 0.0367454, -0.0343107,
      0.0367454, -0.0343107, 0.0367454, -0.0343107, -3.5888e-13, 7.43294e-14,
      -0.665049, 6.74599e-13, 6.70575e-13, 1.91534e-13, 2.08167e-17,
      3.94129e-15, -1.67921e-15, -0.00308388, -0.0257548, -0.00308388,
      -0.0257548, 0.00308388, 0.0257548, 0.00308388, 0.0257548, -3.052e-13,
      1.49269e-13, 6.61554e-13, -0.665049, 6.42431e-13, 2.08396e-13,
      -3.92394e-15, 0, 3.33067e-16, -0.00308388, -0.0257548, 0.00308388,
      0.0257548, 0.00308388, 0.0257548, -0.00308388, -0.0257548, -3.40381e-13,
      1.09607e-13, 6.74016e-13, 6.42403e-13, -0.665049, 1.98716e-13,
      1.68268e-15, -3.43475e-16, 2.42861e-17, -0.00308388, -0.0257548,
      0.00308388, 0.0257548, -0.00308388, -0.0257548, 0.00308388, 0.0257548,
      -0.0733301, -0.21304, -0.250896, -0.250896, -0.250896, -0.0367454,
      0.00308388, 0.00308388, 0.00308388, -1.38778e-17, -0.0654894, 8.63571e-13,
      -0.00963694, 8.65418e-13, -0.00963694, 8.64126e-13, -0.00963694,
      -0.0756726, -0.159214, -0.0655191, -0.0655191, -0.0655191, 0.0343107,
      0.0257548, 0.0257548, 0.0257548, 0.0654894, 1.36609e-17, 0.00963694,
      -1.09752e-12, 0.00963694, -1.09576e-12, 0.00963694, -1.09277e-12,
      -0.0733301, -0.21304, -0.250896, 0.250896, 0.250896, -0.0367454,
      0.00308388, -0.00308388, -0.00308388, -8.63565e-13, -0.00963694,
      4.33681e-18, -0.0654894, 6.12054e-15, -0.00963694, 4.83207e-15,
      -0.00963694, -0.0756726, -0.159214, -0.0655191, 0.0655191, 0.0655191,
      0.0343107, 0.0257548, -0.0257548, -0.0257548, 0.00963694, 1.09758e-12,
      0.0654894, -1.27936e-17, 0.00963694, 2.65369e-15, 0.00963694, 5.03937e-15,
      -0.0733301, -0.21304, 0.250896, 0.250896, -0.250896, -0.0367454,
      -0.00308388, -0.00308388, 0.00308388, -8.65396e-13, -0.00963694,
      -6.11273e-15, -0.00963694, -3.90313e-18, -0.0654894, 7.43416e-15,
      -0.00963694, -0.0756726, -0.159214, 0.0655191, 0.0655191, -0.0655191,
      0.0343107, -0.0257548, -0.0257548, 0.0257548, 0.00963694, 1.09579e-12,
      0.00963694, -2.69272e-15, 0.0654894, -5.5728e-17, 0.00963694, 4.17331e-15,
      -0.0733301, -0.21304, 0.250896, -0.250896, 0.250896, -0.0367454,
      -0.00308388, 0.00308388, -0.00308388, -8.64107e-13, -0.00963694,
      -4.83988e-15, -0.00963694, -7.43156e-15, -0.00963694, 2.77556e-17,
      -0.0654894, -0.0756726, -0.159214, 0.0655191, -0.0655191, 0.0655191,
      0.0343107, -0.0257548, 0.0257548, -0.0257548, 0.00963694, 1.09275e-12,
      0.00963694, -5.06886e-15, 0.00963694, -4.19456e-15, 0.0654894,
      -4.16334e-17;
  diis.Update(0, error2);
  Eigen::MatrixXd error3 = Eigen::MatrixXd::Zero(17, 17);
  error3 << -3.36103e-18, 0.0621516, 3.52141e-13, 3.02803e-13, 3.38022e-13,
      0.0659688, 6.75571e-14, 4.8904e-14, 6.22049e-14, 0.0121774, 0.00560933,
      0.0121774, 0.00560933, 0.0121774, 0.00560933, 0.0121774, 0.00560933,
      -0.0621516, -2.68882e-17, 2.47372e-14, 1.22198e-14, 1.69188e-14, 0.157095,
      -3.08916e-13, -3.27307e-13, -3.19507e-13, 0.0177149, -0.0330234,
      0.0177149, -0.0330234, 0.0177149, -0.0330234, 0.0177149, -0.0330234,
      -3.52141e-13, -2.47368e-14, -4.87891e-18, 1.22461e-15, -5.48932e-16,
      -8.17619e-14, 0.160239, -3.19182e-13, -3.18678e-13, 0.0348853, -0.0441531,
      0.0348853, -0.0441531, -0.0348853, 0.0441531, -0.0348853, 0.0441531,
      -3.02802e-13, -1.22209e-14, -1.22417e-15, -1.11673e-17, -1.76617e-16,
      -1.11732e-13, -3.24306e-13, 0.160239, -3.10646e-13, 0.0348853, -0.0441531,
      -0.0348853, 0.0441531, -0.0348853, 0.0441531, 0.0348853, -0.0441531,
      -3.3802e-13, -1.69193e-14, 5.48281e-16, 1.7705e-16, -5.74627e-18,
      -9.82686e-14, -3.17277e-13, -3.10976e-13, 0.160239, 0.0348853, -0.0441531,
      -0.0348853, 0.0441531, 0.0348853, -0.0441531, -0.0348853, 0.0441531,
      -0.0659688, -0.157095, 8.17558e-14, 1.11734e-13, 9.82721e-14, 2.77556e-17,
      -9.99374e-14, -9.87196e-14, -9.73423e-14, -0.0176436, -0.0598529,
      -0.0176436, -0.0598529, -0.0176436, -0.0598529, -0.0176436, -0.0598529,
      -6.75501e-14, 3.08913e-13, -0.160239, 3.24307e-13, 3.17276e-13,
      9.99478e-14, -3.46945e-18, 1.86136e-15, 1.04604e-15, -0.00608808,
      -0.0306018, -0.00608808, -0.0306018, 0.00608808, 0.0306018, 0.00608808,
      0.0306018, -4.89123e-14, 3.27315e-13, 3.19187e-13, -0.160239, 3.10973e-13,
      9.87127e-14, -1.85789e-15, 0, 5.20417e-16, -0.00608808, -0.0306018,
      0.00608808, 0.0306018, 0.00608808, 0.0306018, -0.00608808, -0.0306018,
      -6.22072e-14, 3.19505e-13, 3.18679e-13, 3.10642e-13, -0.160239,
      9.73388e-14, -1.04777e-15, -5.11743e-16, -2.77556e-17, -0.00608808,
      -0.0306018, 0.00608808, 0.0306018, -0.00608808, -0.0306018, 0.00608808,
      0.0306018, -0.0121774, -0.0177149, -0.0348853, -0.0348853, -0.0348853,
      0.0176436, 0.00608808, 0.00608808, 0.00608808, -2.19551e-18, -0.0562084,
      5.60581e-13, 0.00673288, 5.6097e-13, 0.00673288, 5.59758e-13, 0.00673288,
      -0.00560933, 0.0330234, 0.0441531, 0.0441531, 0.0441531, 0.0598529,
      0.0306018, 0.0306018, 0.0306018, 0.0562084, 3.90313e-18, -0.00673288,
      -6.01511e-13, -0.00673288, -6.01863e-13, -0.00673288, -6.01939e-13,
      -0.0121774, -0.0177149, -0.0348853, 0.0348853, 0.0348853, 0.0176436,
      0.00608808, -0.00608808, -0.00608808, -5.60582e-13, 0.00673288,
      -1.61275e-18, -0.0562084, 2.81444e-15, 0.00673288, 1.93855e-15,
      0.00673288, -0.00560933, 0.0330234, 0.0441531, -0.0441531, -0.0441531,
      0.0598529, 0.0306018, -0.0306018, -0.0306018, -0.00673288, 6.01547e-13,
      0.0562084, -9.54098e-18, -0.00673288, 1.00874e-15, -0.00673288,
      1.74513e-15, -0.0121774, -0.0177149, 0.0348853, 0.0348853, -0.0348853,
      0.0176436, -0.00608808, -0.00608808, 0.00608808, -5.6097e-13, 0.00673288,
      -2.8151e-15, 0.00673288, 3.86247e-18, -0.0562084, 4.46409e-15, 0.00673288,
      -0.00560933, 0.0330234, -0.0441531, -0.0441531, 0.0441531, 0.0598529,
      -0.0306018, -0.0306018, 0.0306018, -0.00673288, 6.01854e-13, -0.00673288,
      -9.97032e-16, 0.0562084, 1.17094e-17, -0.00673288, -5.82867e-16,
      -0.0121774, -0.0177149, 0.0348853, -0.0348853, 0.0348853, 0.0176436,
      -0.00608808, 0.00608808, -0.00608808, -5.59759e-13, 0.00673288,
      -1.94007e-15, 0.00673288, -4.46323e-15, 0.00673288, 0, -0.0562084,
      -0.00560933, 0.0330234, -0.0441531, 0.0441531, -0.0441531, 0.0598529,
      -0.0306018, 0.0306018, -0.0306018, -0.00673288, 6.01939e-13, -0.00673288,
      -1.73819e-15, -0.00673288, 5.82867e-16, 0.0562084, -2.77556e-17;
  diis.Update(0, error3);
  Eigen::VectorXd Coeffs = diis.CalcCoeff();

  Eigen::VectorXd Ref = Eigen::VectorXd::Zero(3);
  Ref << -2.18111, 4.98827, -1.80716;

  bool check_diis = Coeffs.isApprox(Ref, 0.00001);
  if (!check_diis) {
    std::cout << "Ref" << std::endl;
    std::cout << Ref << std::endl;
    std::cout << "Coeffs" << std::endl;
    std::cout << Coeffs << std::endl;
  }
  BOOST_CHECK_EQUAL(check_diis, 1);
}

BOOST_AUTO_TEST_SUITE_END()
